package com.hippo.core.utils.fie;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.util.CollectionUtils;

import java.io.*;
import java.lang.reflect.Field;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;


/**
 * @ClassName BatFileUtil
 * @Description TODO .dat文件处理工具类
 * @Author tangxl
 * @create 2023-04-18 16:39
 **/
public class DatFileUtil<T> {
    private static final Logger log = LoggerFactory.getLogger(DatFileUtil.class);

    /**
     * @Description TODO 生成.dat文件
     * @Author tangxl
     * @Date 2023-04-18 16:40
     * @param path 文件路径
     * @param c 文件内容
     **/
    public void createDatFile(String path, List<T> ts, Class<T> c){
        // 校验文件路径是否正确
        if (!path.endsWith(".dat")) {
            throw new RuntimeException("文件路径不正确");
        }
        // 校验文件是否存在
        File file = new File(path);
        // 获取所有的字段名
        Field[] fieldNames = c.getDeclaredFields();
        // 封装第一行数据
        StringBuilder dataLine = new StringBuilder();
        for (Field fieldName : fieldNames) {
            dataLine.append(fieldName.getName()).append("|");
        }
        dataLine.append("\n");
        // 封装数据行
        for (T t : ts) {
            for (Field fieldName : fieldNames) {
                fieldName.setAccessible(true);
                try {
                    dataLine.append(fieldName.get(t));
                    // 当前字段为最后一个字段时，不需要添加分隔符
                    if (fieldName.getName().equals(fieldNames[fieldNames.length - 1].getName())) {
                        break;
                    }
                    dataLine.append("|");
                } catch (IllegalAccessException e) {
                    e.printStackTrace();
                }
            }
            dataLine.append("\n");
        }
        // 写入文件
        try(
                BufferedOutputStream bufferedOutputStream = new BufferedOutputStream(new FileOutputStream(file));
                ) {
            bufferedOutputStream.write(dataLine.toString().getBytes(), 0, dataLine.toString().getBytes().length);
        }catch (IOException e) {
            e.printStackTrace();
        }

    }

    /**
     * @Description TODO 写入.dat文件
     * @param dataMap 数据
     * @param filePath 文件路径
     */
    public static void createDatFile(List<Map<String,Object>> dataMap,String filePath){
        // 校验文件路径是否正确
        if (!filePath.endsWith(".dat")) {
            throw new RuntimeException("文件路径不正确");
        }
        // 校验数据是否为空
        if (CollectionUtils.isEmpty(dataMap)) {
            log.warn("{}数据为空,不生成文件",filePath);
            return;
        }
        // 校验文件是否存在
        File file = new File(filePath);
        boolean exists = file.exists();
        log.info("{}文件是否存在：{}",filePath,exists);
        // 文件不存在时，创建文件
        if(!exists){
            try {
                file.createNewFile();
            } catch (IOException e) {
                e.printStackTrace();
                log.error("创建文件失败");
            }
        }
        // 封装第一行数据--字段名
        StringBuilder dataLine = new StringBuilder();
        dataMap.get(0).keySet().forEach(key->{
            dataLine.append(key).append("|");
        });
        dataLine.append("\n");
        // 封装数据行
        dataMap.forEach(map->{
            map.values().forEach(value->{
                dataLine.append(value).append("|");
            });
            dataLine.append("\n");
        });
        // 写入文件
        try(
                BufferedOutputStream bufferedOutputStream = new BufferedOutputStream(new FileOutputStream(file));
        ) {
            bufferedOutputStream.write(dataLine.toString().getBytes(), 0, dataLine.toString().getBytes().length);
        }catch (IOException e) {
            e.printStackTrace();
            log.error("写入文件失败");
        }

    }

    /**
     * @Description TODO 读取.dat文件
     * @Author tangxl
     * @Date 2023-04-18 16:40
     * @param filePath
     * @return T
     **/
    public List<T> readDatFile(String filePath, Class<T> c) {
        // 判断文件是否是.dat文件
        if (!filePath.endsWith(".dat")) {
            throw new RuntimeException("文件不是.dat文件");
        }
        // 判断文件是否存在
        File file = new File(filePath);
        if (!file.exists()) {
            throw new RuntimeException("文件不存在");
        }
        StringBuilder dataLine = new StringBuilder();
        // 读取文件
        try(
                BufferedInputStream bufferedInputStream = new BufferedInputStream(new FileInputStream(file));
                ) {
            byte[] bytes = new byte[1024];
            int len;
            while ((len = bufferedInputStream.read(bytes)) != -1) {
                dataLine.append(new String(bytes, 0, len));
            }
            // 将文件内容转换为List
            String[] dataLines = dataLine.toString().split("\n");
            // 获取所有的字段名
            Field[] fieldNames = c.getDeclaredFields();
            // 封装数据
            List<T> ts = new ArrayList<>();
            for (int i = 1; i < dataLines.length; i++) {
                String[] data = dataLines[i].split("\\|");
                T t = c.newInstance();
                for (int j = 0; j < data.length; j++) {
                    // 设置字段可访问
                    fieldNames[j].setAccessible(true);
                    // 根据字段数据类型设置字段值
                    if (fieldNames[j].getType().equals(Integer.class)) {
                        fieldNames[j].set(t, Integer.valueOf(data[j]));
                    } else if (fieldNames[j].getType().equals(BigDecimal.class)) {
                        fieldNames[j].set(t, BigDecimal.valueOf(Double.valueOf(data[j])));
                    } else if (fieldNames[j].getType().equals(Float.class)) {
                        fieldNames[j].set(t, Float.valueOf(data[j]));
                    } else if (fieldNames[j].getType().equals(Integer.class)){
                        fieldNames[j].set(t, Integer.valueOf(data[j]));
                    } else if (fieldNames[j].getType().equals(Float.class)){
                        fieldNames[j].set(t, Float.valueOf(data[j]));
                    } else if (fieldNames[j].getType().equals(Double.class)){
                        fieldNames[j].set(t, Double.valueOf(data[j]));
                    } else if (fieldNames[j].getType().equals(Long.class)){
                        fieldNames[j].set(t, Long.valueOf(data[j]));
                    } else if (fieldNames[j].getType().equals(Boolean.class)){
                        fieldNames[j].set(t, Boolean.valueOf(data[j]));
                    } else if (fieldNames[j].getType().equals(Character.class)){
                        fieldNames[j].set(t, Character.valueOf(data[j].charAt(0)));
                    } else if (fieldNames[j].getType().equals(Byte.class)){
                        fieldNames[j].set(t, Byte.valueOf(data[j]));
                    } else if (fieldNames[j].getType().equals(Short.class)){
                        fieldNames[j].set(t, Short.valueOf(data[j]));
                    } else if (fieldNames[j].getType().equals(String.class)){
                        fieldNames[j].set(t, data[j]);
                    }
                    fieldNames[j].set(t, data[j]);
                }
                ts.add(t);
            }
            return ts;
        }catch (Exception e) {
            e.printStackTrace();
        }

        return null;
    }

    public static void main(String[] args) throws IOException {
//        DatFileUtil datFileUtil = new DatFileUtil();
//        /**
//         * 测试数据写入文件
//         */
//        // 循环生成数据
//        List<DataExample> dataExamples = new ArrayList<>();
//        for (int i = 0; i < 600000; i++) {
//            DataExample dataExample = new DataExample();
//            dataExample.setId(i);
//            dataExample.setName("张三" + i);
//            dataExample.setAge(18);
//            dataExample.setMoney(BigDecimal.valueOf(599.99));
//            dataExample.setNumber(12345.45545f);
//            dataExamples.add(dataExample);
//        }
//        // 生成文件
//        datFileUtil.createDatFile("study-commons/core/src/main/resources/file/data.dat", dataExamples, DataExample.class);
//        System.out.println("写入数据成功");

        /**
         * 创建.dat文件
         */
        File file = new File("mysql/data/test.dat");
        // 打印文件当前目录
        System.out.println(file.getAbsolutePath());
        file.createNewFile();

        /**
         * 读取.dat文件
         */
//        List<Data> data = datFileUtil.readDatFile("study-commons/core/src/main/resources/file/data.dat", Data.class);
//        System.out.println("读取数据成功："+data);
    }

}
